package com.ecoolex.ying.space.core.manager;

import com.ecoolex.framework.common.enums.ResultCode;
import com.ecoolex.framework.common.pojo.Page;
import com.ecoolex.framework.common.pojo.Pagination;
import com.ecoolex.framework.common.pojo.Sorting;
import com.ecoolex.framework.common.pojo.Sortings;
import com.ecoolex.framework.common.util.BizAssert;
import com.ecoolex.framework.common.util.Check;
import com.ecoolex.ying.space.core.dao.OutsourcingPackagedDAO;
import com.ecoolex.ying.space.entity.OutsourcingPackaged;
import com.ecoolex.ying.space.entity.OutsourcingPackaged.Column;
import com.ecoolex.ying.space.entity.OutsourcingPackagedExample;
import com.ecoolex.ying.space.entity.OutsourcingPackagedExample.Criteria;
import com.ecoolex.ying.space.entity.OutsourcingPackagedGoods;
import com.ecoolex.ying.space.entity.WholeHouseCaseItems;

import java.math.BigDecimal;
import java.sql.Date;
import java.time.Instant;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class OutsourcingPackagedManager {
	
    @Autowired
    private OutsourcingPackagedDAO dao;
    
    @Autowired
    private OutsourcingPackagedGoodsManager outsourcingPackagedGoodsManager;
    
    @Autowired
    private OutsourcingGoodsManager outsourcingGoodsManager;
    
    @Autowired
    private WholeHouseCaseItemsManager wholeHouseCaseItemsManager;
    
    @Autowired
    private UserWorksShoppingManager userWorksShoppingManager;
    
    @Autowired
    private ShareImageManager shareImageManager;
    
    private void verify(OutsourcingPackaged record,List<Integer> outsourcingGoodsIds) {
		BizAssert.isTrue(Check.notNullOrTrimEmpty(record.getName()), ResultCode.VERIFY.build(10), "外购套餐名称为空");
		BizAssert.isTrue(Check.notNullAndGteZero(record.getRetailPrice()), ResultCode.VERIFY.build(11), "零售价格为空");
		BizAssert.isTrue(Check.notNullOrTrimEmpty(record.getBuyLink()), ResultCode.VERIFY.build(13), "购买链接为空");
		BizAssert.isTrue(Check.isGreatThanEqual(outsourcingGoodsIds.size(), 0), ResultCode.VERIFY.build(14), "至少选择一个商品");
		for(Integer outsourcingGoodsId:outsourcingGoodsIds) {
			BizAssert.isTrue(Check.notNull(outsourcingGoodsManager.getOnlineById(outsourcingGoodsId)), ResultCode.VERIFY.build(15), "商品已下线，ID={"+outsourcingGoodsId+"}");
		}
	}
    
    @Transactional
    public OutsourcingPackaged add(OutsourcingPackaged record,List<Integer> outsourcingGoodsIds, String createUser ) {
    	verify(record,outsourcingGoodsIds);
    	
    	record.setOnline(false);
    	record.setDeleted(OutsourcingPackaged.NOT_DELETED);
		record.setCreateUser(createUser);
		record.setCreateTime(Date.from(Instant.now()));
		record.setUpdateUser(createUser);
		record.setUpdateTime(Date.from(Instant.now()));
		dao.insert(record);
		
		// 添加分享图片
        shareImageManager.addShareImage(record.getCoverImage());
		
		outsourcingPackagedGoodsManager.add(record, outsourcingGoodsIds, createUser);
    	return record;
    }
    
    @Transactional
    public OutsourcingPackaged edit(OutsourcingPackaged record,List<Integer> outsourcingGoodsIds, String updateUser) {
    	verify(record,outsourcingGoodsIds);
    	
    	record.setUpdateUser(updateUser);
    	record.setUpdateTime(Date.from(Instant.now()));
    	dao.updateByPrimaryKeySelective(record, Column.excludes(Column.online,Column.deleted,Column.createUser,Column.createTime));
    	
    	// 添加分享图片
        shareImageManager.addShareImage(record.getCoverImage());
    	
    	outsourcingPackagedGoodsManager.update(record, outsourcingGoodsIds, updateUser);
    	return record;
    }
    
    @Transactional
    public void delete(OutsourcingPackaged record,String updateUser) {
    	boolean flag = userWorksShoppingManager.getByOutsourcingPackagedId(record.getOutsourcingPackagedId());
    	BizAssert.isTrue(flag,ResultCode.VERIFY.build(10), "有作品购物使用了该套餐");
    	record.setDeleted(OutsourcingPackaged.IS_DELETED);
    	record.setUpdateUser(updateUser);
    	record.setUpdateTime(Date.from(Instant.now()));
    	dao.updateByPrimaryKeySelective(record, Column.deleted,Column.updateTime,Column.updateUser);
    	
    	outsourcingPackagedGoodsManager.deleteByOutsourcingPackagedId(record, updateUser);
    }
    
    public void online(OutsourcingPackaged record,String updateUser) {
    	record.setOnline(true);
    	record.setUpdateUser(updateUser);
    	record.setUpdateTime(Date.from(Instant.now()));
    	dao.updateByPrimaryKeySelective(record, Column.online,Column.updateTime,Column.updateUser);
    }
    
    public void offline(OutsourcingPackaged record,String updateUser) {
    	record.setOnline(false);
    	record.setUpdateUser(updateUser);
    	record.setUpdateTime(Date.from(Instant.now()));
    	dao.updateByPrimaryKeySelective(record, Column.online,Column.updateTime,Column.updateUser);
    }
    
    public OutsourcingPackaged getById(Integer outsourcingPackagedId) {
    	return dao.selectByPrimaryKeyWithLogicalDelete(outsourcingPackagedId, OutsourcingPackaged.NOT_DELETED);
    }
    
    public boolean getOnlineById(List<OutsourcingPackagedGoods> packagedGoodsList) {
    	
    	for (OutsourcingPackagedGoods outsourcingPackagedGoods : packagedGoodsList) {
    		OutsourcingPackagedExample example = new OutsourcingPackagedExample();
        	Criteria criteria = example.createCriteria();
        	criteria.andOutsourcingPackagedIdEqualTo(outsourcingPackagedGoods.getOutsourcingPackagedId());
        	criteria.andOnlineEqualTo(true);
        	criteria.andDeletedEqualTo(OutsourcingPackaged.NOT_DELETED);
        	OutsourcingPackaged outsourcingPackaged = dao.selectOneByExample(example);
        	if(Check.notNull(outsourcingPackaged)) {
        		return false;
        	}
		}
    	return true;
    }
    
    public Pagination<OutsourcingPackaged> query(String name,Boolean online, Sorting[] sorts, Page page){
    	OutsourcingPackagedExample example = new OutsourcingPackagedExample();
    	Criteria criteria = example.createCriteria();
    	if(Check.notNullOrTrimEmpty(name)) {
    		criteria.andNameLike('%' + name
			+ '%');
    	}
    	if(Check.notNull(online)) {
    		criteria.andOnlineEqualTo(online);
    	}
    	criteria.andDeletedEqualTo(OutsourcingPackaged.NOT_DELETED);
		example.orderBy(Sortings.builder(sorts).verify(Column::valueOf).toSql());
		example.setOffset(page.getFirstIndex());
		example.setRows(page.getPageSize());

		return Pagination.create(page, dao.countByExample(example), () -> dao.selectByExample(example));
    }
    
    public OutsourcingPackaged getByIdForH5(Integer outsourcingPackagedId) {
    	OutsourcingPackagedExample example = new OutsourcingPackagedExample();
    	Criteria criteria = example.createCriteria();
    	criteria.andOutsourcingPackagedIdEqualTo(outsourcingPackagedId);
    	criteria.andOnlineEqualTo(true);
    	criteria.andDeletedEqualTo(OutsourcingPackaged.NOT_DELETED);
    	return dao.selectOneByExampleWithBLOBs(example);
    }
    
    public Pagination<OutsourcingPackaged> queryForH5(Sorting[] sorts, Page page){
    	OutsourcingPackagedExample example = new OutsourcingPackagedExample();
    	Criteria criteria = example.createCriteria();
    	criteria.andOnlineEqualTo(true);
    	criteria.andDeletedEqualTo(OutsourcingPackaged.NOT_DELETED);
		example.orderBy(Sortings.builder(sorts).verify(Column::valueOf).toSql());
		example.setOffset(page.getFirstIndex());
		example.setRows(page.getPageSize());

		return Pagination.create(page, dao.countByExample(example), () -> dao.selectByExample(example));
    }
    
    public BigDecimal getTotalRetailPriceByPackagedId(Integer caseId) {
    	BigDecimal totalRetailPrice = new BigDecimal(0);
    	List<WholeHouseCaseItems> itemsList = wholeHouseCaseItemsManager.getByCaseId(caseId);
    	for (WholeHouseCaseItems wholeHouseCaseItems : itemsList) {
			if(Check.notNullAndGtZero(wholeHouseCaseItems.getOutsourcingPackagedId())) {
				OutsourcingPackaged outsourcingPackaged = getByIdForH5(wholeHouseCaseItems.getOutsourcingPackagedId());
				if(Check.notNull(outsourcingPackaged)) {
					totalRetailPrice = totalRetailPrice.add(outsourcingPackaged.getRetailPrice());
				}
			}
		}
    	return totalRetailPrice;
    }
    
    public Pagination<OutsourcingPackaged> queryOutsourcingPackagedByGoodsId(Integer outsourcingGoodsId, Page page){
    	return Pagination.create(page,
    		dao.countByGoodsId(outsourcingGoodsId),
    		() -> dao.queryByGoodsId(outsourcingGoodsId, page));
    }
}